/*******
mesQueue.c:

@author Will Lamond

An implementation of a message queue data structure.
*******/

#include "glob.h"

//int main() {
//	MSQUEUE queue;
//	mQueueInit(&queue);
//
//	int i = 1;
//	int j = 2;
//	int k = 3;
//
//	char m1[40] = "The first message!\n";
//	char m2[40] = "The second message!\n";
//	char m3[40] = "The third message!\n";
//
//	char c1[40];
//	char c2[40];
//	char c3[40];
//
//	enqueue(&queue, i, m1);
//	enqueue(&queue, j, m2);
//	enqueue(&queue, k, m3);
//
//	printf("The head index is %d and message: %s\n", dequeue(&queue, c1), c1);
//	printf("The head index is %d and message: %s\n", dequeue(&queue, c2), c2);
//	printf("The head index is %d and message: %s\n", dequeue(&queue, c3), c3);
//
//
//	return 1;
//}

/*enqueue:
 *
 * Put a new MSQNODE on the MSQUEUE q with index in and message mess[].
 *
 *Usage: enqueue(&q, in, mess);
 */

void mEnqueue(MSQUEUE *q, int in, char *mess) {
	MSQNODE *new = malloc(sizeof(MSQNODE));
	new->index = in;

	new->message = malloc(40 * sizeof(char));
	memcpy(new->message, mess, 40);
	new->next = NULL;

	if (!(q->head)) {
		(q->head) = new;
		(q->tail) = new;
	}
	else{
		(q->tail)->next = new;
		q->tail = new;
	}
}

/* mdequeue:
 *
 * Remove the head MSQNODE from the MSQUEUE q and put the message into char mess[].
 *
 *Usage: dequeue(&q, mess);
 */

int mDequeue(MSQUEUE *q, char *mess) {
	if (!(q->head)) {
		//printf("Message queue is empty!\n");
		return -1;
	}
	else {
		int ret;
		ret = (q->head)->index;
		memcpy(mess, (q->head)->message, sizeof(char)*40);
		MSQNODE *temp = (q->head);
		q->head = (q->head)->next;
		free(temp);
		temp = NULL;
		return ret;
	}

}



/*mdequeuen:
 *
 * Get the message mess from the specific process with PID n from the desired message queue q.
 *
 * Usage: mdequeuen(&q, n, mess);
 */

int mDequeuen(MSQUEUE *q, int n, char *mess) {
	if (!(q->head)) //occurs when q is empty
		return (-1);
	MSQNODE *temp;
	temp = q->head;
	if (temp->index == n) {
		memcpy(mess, temp->message, sizeof(char) * 40); //copy message to message buffer
		(q->head) = (q->head)->next;
		free(temp); //free the old node
		temp = NULL;
		return 1;
	} else {
		MSQNODE *last = temp; //hold the last MSQNODE in order to preserve the queue.
		while ((temp = temp->next)) { //both reassign temp and check to see if it's null
			if ((temp->index) == n) {
				memcpy(mess, temp->message, sizeof(char) * 40);
				(last->next) = temp->next;
				free(temp); //free the old node
				temp = NULL;
				return 1;
			} else {
				last = temp;
			}
		}
		return -1;
	}
}


/* mQueueInit:
 *
 * Initialize the MSQUEUE q.
 *
 *Usage: mQueueInit(&q);
 */

void mQueueInit(MSQUEUE **q) {
	*q = malloc(sizeof(MSQUEUE));
	(*q)->head = NULL;
	(*q)->tail = NULL;
}

